package util.form.respuesta;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import util.patron.command.Command1;

public class GrupoInput {

	private final List<Input> inputs;
	private Map<String,Input1> inputs1Todos = new HashMap<String,Input1>();
	
	public GrupoInput() {
		this.inputs = new ArrayList<Input>();
	}

	public final GrupoInput agregar(Input input) {
		if(input instanceof Input1) {
			Input1 in = (Input1) input;
			onAgregarInput(in);
		}
		else if(input instanceof Input2) {
			Input2 in = (Input2) input;
			onAgregarInput(in.getInput1());
			onAgregarInput(in.getInput2());
		}	
		this.inputs.add(input);
		
		postAgregar(input);
		
		return this;
	}
	
	protected void postAgregar(Input input) {
		
	}
	
	private void onAgregarInput(Input1 input) {
		String nombre = input.getPregunta().getNombre();
		if(nombre!=null) {
			inputs1Todos.put(nombre.toUpperCase(Locale.getDefault()), input);		
		}
	}
	
	public String findValor(String nombre) {
		if(nombre!=null) {		
			Input1 in = inputs1Todos.get(nombre.toUpperCase(Locale.getDefault()));
			if(in!=null)
				return in.getValor();
		}
		return null;
	}
	
	public GrupoInput setRequerido(boolean requerido) {
		for(Input in: inputs) {
			in.setRequerido(requerido);
		}
		return this;
	}
	
	public GrupoInput setRelevancia(boolean relevancia) {
		for(Input in: inputs) {
			in.setRelevancia(relevancia);
		}
		return this;
	}
	
	public boolean contieneValor(String valor) {
		for(Input in: inputs) {
			if(in.contieneValor(valor)) {
				return true;
			}
		}
		return false;
	}
	
	
	public void iterar(Command1<Input> comando) throws Exception {
		for(Input in: inputs) {
			comando.execute(in);
		}
	}
	
	public List<Input> getInputsTotal() {
		List<Input> lista = new ArrayList<Input>();
		getInputsTotal_recursivo(lista,inputs);
		return lista;
	}
	
	private void getInputsTotal_recursivo(List<Input> lista, List<Input> inputs) {
		for(Input input : inputs) {
			lista.add(input);			
			GrupoInput subf = input.getSubInputs();
			getInputsTotal_recursivo(lista,subf.inputs);
		}
	}
	
	private List<Input1> getInputs1Total() {
		List<Input1> lista = new ArrayList<Input1>();
		getInputs1Total_recursivo(lista,inputs);
		return lista;
	}
	
	private void getInputs1Total_recursivo(List<Input1> lista, List<Input> inputs) {
		for(Input input : inputs) {
			if(input instanceof Input1) {
				Input1 in = (Input1) input;
				lista.add(in);
			}
			else if(input instanceof Input2) {
				Input2 in = (Input2) input;
				Input1 in1 = in.getInput1();
				Input1 in2 = in.getInput2();
				lista.add(in1);
				lista.add(in2);
			}
			
			GrupoInput subf = input.getSubInputs();
			getInputs1Total_recursivo(lista,subf.inputs);
		}
	}
	
	public List<String> getNombresInputsEnTotal() {
		List<String> lista = new ArrayList<String>();
		List<Input1> inputs1 = getInputs1Total();
		for(Input1 in : inputs1) {
			if(in.getPregunta().getNombre()!=null)
				lista.add(in.getPregunta().getNombre());
		}
		return lista;
	}
	
	public RegistroImpl getRegistro() {
		RegistroImpl registro = new RegistroImpl();		
		agregarInputs_recursivo(registro,inputs);		
		return registro;
	}
	
	public RegistroImpl getRegistroNoRelevante() {
		RegistroImpl registro = new RegistroImpl();		
		agregarInputs_recursivo(registro,inputs);		
		return registro;
	}
		
	public Collection<Input> getInputs() {
		return inputs;
	}
	
	private void agregarInputs_recursivo(RegistroImpl registro, List<Input> inputs) {
		for(Input input : inputs) {
			if(input instanceof Input1) {
				Input1 in = (Input1) input;
				String nombre = in.getPregunta().getNombre();
				if(nombre!=null) {
					if(!registro.isExisteValor(nombre)) {//si el valor es nuevo
						registro.agregar(nombre,in.getValorRelevante());
					}
					else {//si ya existe un valor con ese nombre
						if(in.isRelevante()) {//reemplaza el valor, solo si es el nuevo valor es relevante
							registro.agregar(nombre,in.getValorRelevante());
						}
					}
				}
			}
			else if(input instanceof Input2) {
				Input2 in = (Input2) input;
				Input1 in1 = in.getInput1();
				Input1 in2 = in.getInput2();				
				registro.agregar(in1.getPregunta().getNombre(),in1.getValorRelevante());
				registro.agregar(in2.getPregunta().getNombre(),in2.getValorRelevante());
			}
			
			GrupoInput subf = input.getSubInputs();
			agregarInputs_recursivo(registro, subf.inputs);
		}
	}
	
	protected final boolean onPostGuardar() throws Exception {
		boolean guarda = false;
		for(Input in : inputs) {
			if(in.onPostGuardar())
				guarda = true;
		}
		return guarda;
	}
	
	public void agregar(String nombre, String valor) throws Exception {
		InputString in = new InputString();
		in.setNombre(nombre);
		in.setValor(valor);
		agregar(in);
	}	
	
	public void agregar(String nombre, Input1 input) throws Exception {		
		input.setNombre(nombre);
		agregar(input);
	}
		
	public void agregar(String nombre1, String nombre2, Input2 input) throws Exception {		
		input.getInput1().setNombre(nombre1);		
		input.getInput2().setNombre(nombre2);
		agregar(input);
	}

}
